package com.biz.primus.ms.oms.service.returns;

import com.biz.primus.base.exception.BizSilentException;
import com.biz.primus.base.vo.PageResult;
import com.biz.primus.common.utils.Copier;
import com.biz.primus.common.utils.CopyUtils;
import com.biz.primus.model.oms.enums.CancelType;
import com.biz.primus.model.oms.vo.OmsOrderReturnVo;
import com.biz.primus.model.oms.vo.OmsRefundDetailVo;
import com.biz.primus.model.oms.vo.OrderRefundQueryVo;
import com.biz.primus.model.oms.vo.OrderReturnQueryVo;
import com.biz.primus.model.oms.vo.returns.OmsRefundVo;
import com.biz.primus.model.oms.vo.returns.OmsReturnVo;
import com.biz.primus.ms.base.service.AbstractBaseService;
import com.biz.primus.ms.oms.dao.po.OmsOrder;
import com.biz.primus.ms.oms.dao.po.OmsOrderItem;
import com.biz.primus.ms.oms.dao.po.OrderPaymentInfo;
import com.biz.primus.ms.oms.dao.po.returns.OmsRefund;
import com.biz.primus.ms.oms.dao.po.returns.OmsReturn;
import com.biz.primus.ms.oms.dao.po.returns.OmsReturnItem;
import com.biz.primus.ms.oms.dao.repository.OmsOrderRepository;
import com.biz.primus.ms.oms.dao.repository.OmsOrderReturnRepository;
import com.biz.primus.ms.oms.dao.repository.OmsPaymentRepository;
import com.biz.primus.ms.oms.dao.repository.OmsRefundRepository;
import com.biz.primus.ms.oms.dao.specification.OmsOrderRefundSpecification;
import com.biz.primus.ms.oms.dao.specification.OmsOrderReturnSpecification;
import com.biz.primus.model.oms.exception.OmsExceptions;
import com.biz.primus.ms.oms.trans.ReturnConverter;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;


@Service
@Slf4j
public class OrderReturnQueryServiceImpl extends AbstractBaseService implements  OrderReturnQueryService{


    @Autowired
    private OmsOrderReturnRepository omsOrderReturnRepository;

    @Autowired
    private OmsOrderRepository omsOrderRepository;

    @Autowired
    private OmsRefundRepository omsRefundRepository;

    @Autowired
    private ReturnConverter returnConverter;

    @Autowired
    private OmsPaymentRepository omsPaymentRepository;

    @Override
    public PageResult<OmsOrderReturnVo> findReturns(OrderReturnQueryVo query) {
        Page<OmsReturn> page =  omsOrderReturnRepository.findAll(new OmsOrderReturnSpecification(query),query.toPageRequest());
        List<OmsOrderReturnVo> result = page.getContent().stream().map(returnConverter::po2vo).collect(Collectors.toList());
        return PageResult.of(page.getNumber(),page.getTotalPages(),result);
    }

    @Override
    public OmsOrderReturnVo orderReturnQueryDetail(String depotCode,String returnCode) {
        OmsReturn omsReturn = omsOrderReturnRepository.findByReturnCode(returnCode);

        if(Objects.isNull(omsReturn)){
            throw  new BizSilentException(OmsExceptions.ORDER_NOT_FOUNT);
        }

        if(omsReturn.getCancelType() != CancelType.none){
            throw new BizSilentException(OmsExceptions.ORDER_CANCEL);
        }

        if(!Objects.equals(depotCode,omsReturn.getDepotCode())){
            throw  new BizSilentException(OmsExceptions.DEPOT_ERROR);
        }

        OmsOrderReturnVo returnVo = returnConverter.po2vo(omsReturn);
        List<OmsReturnItem> rItems = omsReturn.getItems();
        List<Long> itemIds = rItems.stream().map(OmsReturnItem::getItemId).collect(Collectors.toList());
        List<OmsOrderItem> oItems = omsOrderRepository.findOrderItemsById(omsReturn.getOrderId(), itemIds);
        returnVo.setItems(returnConverter.poItems2voItems(rItems, oItems));

        return returnVo;
    }

    @Override
    public PageResult<OmsRefundVo> managementRefundQueryList(OrderRefundQueryVo orderQueryVo) {
        Page<OmsRefund>  omsRefundPage = omsRefundRepository.findAll(new OmsOrderRefundSpecification(orderQueryVo),orderQueryVo.toPageRequest());
        List<OmsRefundVo> result = omsRefundPage.getContent().stream()
                .map(po -> Copier.from(po).to(new OmsRefundVo())).collect(Collectors.toList());
        return   PageResult.of(omsRefundPage.getNumber(),omsRefundPage.getTotalPages(),result);
    }

    @Override
    public PageResult<OmsReturnVo> managementReturnQueryList(OrderReturnQueryVo orderReturnQueryVo) {
        Page<OmsReturn> omsReturns = omsOrderReturnRepository.findAll(new OmsOrderReturnSpecification(orderReturnQueryVo),orderReturnQueryVo.toPageRequest());


        List<OmsReturnVo> result = omsReturns.getContent().stream()
                .map(po -> Copier.from(po).to(new OmsReturnVo())).collect(Collectors.toList());

        List<Long> ids = result.stream().map(OmsReturnVo::getOrderId).collect(Collectors.toList());
        List<OmsOrder> omsOrders = omsOrderRepository.findAll(ids);
        ImmutableMap<Long, OmsOrder> itemMap = Maps.uniqueIndex(omsOrders, OmsOrder::getId);

        List<OmsReturnVo> omsReturnVos = result.stream().map((OmsReturnVo i) ->{
            OmsOrder omsOrder =  itemMap.get(i.getOrderId());
            i.setOrderState(omsOrder.getState());
            i.setOrderDeliveryType(omsOrder.getDeliveryType());
            return i;
        }).collect(Collectors.toList());

        return   PageResult.of(omsReturns.getNumber(),omsReturns.getTotalPages(),omsReturnVos);
    }

    @Override
    public OmsReturnVo auditReturnDetail(String returnCode) {
        OmsReturn omsReturn = omsOrderReturnRepository.findByReturnCode(returnCode);
        OmsOrder omsOrder = omsOrderRepository.findOne(omsReturn.getOrderId());
        OmsReturnVo omsReturnVo = returnConverter.po2OmsReturnVo(omsReturn);
        omsReturnVo.setUserMobile(omsOrder.getUserMobile());
        omsReturnVo.setUserName(omsOrder.getUserName());
        omsReturnVo.setOrderAmount(omsOrder.getOrderAmount());

        List<OrderPaymentInfo> orderPaymentInfos = omsPaymentRepository.findByOrderId(omsReturn.getOrderId());
        List<String> paymentWays = orderPaymentInfos.stream().map(OrderPaymentInfo::getPaymentWayText).collect(Collectors.toList());

        omsReturnVo.setPaymentWays(paymentWays);
        return omsReturnVo;
    }

    @Override
    public OmsRefundDetailVo getRefundDetail(String refundCode) {
       OmsRefund omsRefund = omsRefundRepository.findByRefundCode(refundCode);
       OmsReturn omsReturn = omsOrderReturnRepository.findOne(omsRefund.getReturnId());

       OmsRefundVo omsRefundVo = new OmsRefundVo();
       OmsReturnVo omsReturnVo = new OmsReturnVo();
       OmsRefundDetailVo omsRefundDetailVo =new OmsRefundDetailVo();
       CopyUtils.copyNotNullProperies(omsRefund,omsRefundVo);
       CopyUtils.copyNotNullProperies(omsReturn,omsReturnVo);
       omsRefundDetailVo.setOmsRefundVo(omsRefundVo);
       omsRefundDetailVo.setOmsReturnVo(omsReturnVo);
       omsRefundDetailVo.setOrderCode(omsReturn.getOrderCode());
       return omsRefundDetailVo;
    }
}
